/* globals window */
import { ApolloClient, InMemoryCache } from '@apollo/client/core';
import { SchemaLink } from '@apollo/client/link/schema';
import { makeExecutableSchema } from 'graphql-tools';

const cache = new InMemoryCache();
const defaultDashboardItems = [];

const getDashboardItems = () => JSON.parse(window.localStorage.getItem('dashboardItems')) ||
  defaultDashboardItems;

const setDashboardItems = (items) => window.localStorage.setItem('dashboardItems', JSON.stringify(items));

const nextId = () => {
  const currentId =
    parseInt(window.localStorage.getItem('dashboardIdCounter'), 10) || 1;
  window.localStorage.setItem('dashboardIdCounter', (currentId + 1).toString());
  return currentId.toString();
};

const toApolloItem = (i) => ({ ...i, __typename: 'DashboardItem' });

const typeDefs = `
  type DashboardItem {
    id: String!
    layout: String
    vizState: String
    name: String
  }

  input DashboardItemInput {
    layout: String
    vizState: String
    name: String
  }

  type Query {
    dashboardItems: [DashboardItem]
    dashboardItem(id: String!): DashboardItem
  }

  type Mutation {
    createDashboardItem(input: DashboardItemInput): DashboardItem
    updateDashboardItem(id: String!, input: DashboardItemInput): DashboardItem
    deleteDashboardItem(id: String!): DashboardItem
  }
`;
const schema = makeExecutableSchema({
  typeDefs,
  resolvers: {
    Query: {
      dashboardItems() {
        const dashboardItems = getDashboardItems();

        return dashboardItems.map(toApolloItem);
      },

      dashboardItem(_, { id }) {
        const dashboardItems = getDashboardItems();
        return toApolloItem(dashboardItems.find((i) => i.id.toString() === id));
      },
    },
    Mutation: {
      createDashboardItem: (_, { input: { ...item } }) => {
        const dashboardItems = getDashboardItems();
        item = { ...item, id: nextId(), layout: JSON.stringify({}) };
        dashboardItems.push(item);
        setDashboardItems(dashboardItems);

        return toApolloItem(item);
      },
      updateDashboardItem: (_, { id, input: { ...item } }) => {
        const dashboardItems = getDashboardItems();
        item = Object.keys(item)
          .filter((k) => !!item[k])
          .map((k) => ({
            [k]: item[k],
          }))
          .reduce((a, b) => ({ ...a, ...b }), {});
        const index = dashboardItems.findIndex((i) => i.id.toString() === id);
        dashboardItems[index] = { ...dashboardItems[index], ...item };
        setDashboardItems(dashboardItems);

        return toApolloItem(dashboardItems[index]);
      },
      deleteDashboardItem: (_, { id }) => {
        const dashboardItems = getDashboardItems();
        const index = dashboardItems.findIndex((i) => i.id.toString() === id);
        const [removedItem] = dashboardItems.splice(index, 1);
        setDashboardItems(dashboardItems);

        return toApolloItem(removedItem);
      },
    },
  },
});

export default new ApolloClient({
  cache,
  link: new SchemaLink({
    schema,
  }),
});
